import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;



public class CardReader {
	Document list1;
	Document list2;
	//reads the xml documents in to be used later
	
	public static final String CARD_LIST_XML = "src/CardList.xml";
	
	public CardReader(){
		parseLists();
	}
	
	private void parseLists(){
		//get the factory
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

		try {
			//Using factory get an instance of document builder
			DocumentBuilder db = dbf.newDocumentBuilder();

			//parse using builder to get DOM representation of the XML file
			list1 = db.parse(CARD_LIST_XML);
			list2 = db.parse(CARD_LIST_XML);
		}catch(ParserConfigurationException pce) {
			pce.printStackTrace();
		}catch(SAXException se) {
			se.printStackTrace();
		}catch(IOException ioe) {
			ioe.printStackTrace();
		}
	}
	//
	public Deck parseDeck(Document list, Player user, Player opponent){
		//get the root element
		ArrayList<Card> cardList = new ArrayList<Card>();
		Element docEle = list.getDocumentElement();
		NodeList nl = docEle.getElementsByTagName("card");
		if(nl != null && nl.getLength() > 0) {
			for(int i = 0 ; i < nl.getLength();i++) {

				//get the employee element
				Element el = (Element)nl.item(i);

				//get the Employee object
				Card card = createCard(el, user, opponent);

				//add it to list
				cardList.add(card);
			}
		}
		return new Deck(cardList);
	}

	private String getTextValue(Element info, String tagName) {
		String textVal = null;
		NodeList nl = info.getElementsByTagName(tagName);
		try{
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}
		}
		catch(Exception e){System.out.println("Cannot find or improper formatting for: " + tagName + " for attribute " + info.toString());}

		return textVal;
	}


	/**
	 * Calls getTextValue and returns a int value
	 */
	private int getIntValue(Element ele, String tagName) {
		//in production application you would catch the exception
		String text = getTextValue(ele,tagName);
		if (text != null)
		return Integer.parseInt(text);
		else
		return -10;
	}

	private Card createCard(Element info, Player user, Player opponent){
		ArrayList<EffectActive> activeList = new ArrayList<EffectActive>();
		ArrayList<EffectPassive> passiveList = new ArrayList<EffectPassive>();
		String name = getTextValue(info,"name");
		int egoCost = getIntValue(info,"egoCost");
		int priority = getIntValue(info,"priority");
		String suit = getTextValue(info,"suit");
		String activeDescription = getTextValue(info,"activeDescription");
		String passiveDescription = getTextValue(info,"passiveDescription");
		if(name == null || egoCost == -10 || priority == -10 || suit == null || passiveDescription == null || (activeDescription == null))
			System.out.println("For card: " + name);
		
		NodeList actives = info.getElementsByTagName("active");
		if(actives != null && actives.getLength() > 0) {
			for(int i = 0 ; i < actives.getLength();i++) {
				Element el = (Element)actives.item(i);
				String type = getTextValue(el,"type") + "Command";
				String subtype = getTextValue(el,"subType");
				if(subtype == null) subtype = "";
				int magnitude = getIntValue(el,"magnitude");
				
				try{
				//Command activeEffect = (Command)EffectActive.createEffect(type);
					activeList.add(new EffectActive(type, magnitude, user, opponent, subtype));
				}
				catch(Exception e){
					System.out.println("Class" + type + " not found.");
				}			
			}
		}
		NodeList passives = info.getElementsByTagName("passive");
		if(passives != null && passives.getLength() > 0) {
			for(int i = 0 ; i < passives.getLength();i++) {

				Element el = (Element)passives.item(i);
				String type = getTextValue(el,"type");
				int magnitude = getIntValue(el,"magnitude");
				
				try{
					//Command activeEffect = (Command)Class.forName(type).newInstance();
					passiveList.add(new EffectPassive(type, magnitude));
					}
					catch(Exception e){
						System.out.println("Class " + type + "() not found.");
					}	
			}
		}

		//Create a new Employee with the value read from the xml nodes
		Card e = new Card(name, activeDescription, passiveDescription, egoCost, priority, suit, activeList, passiveList);

		return e;
	}	

}
